#include "stdafx.h"
#include "stdres.h"
#include "app.h"
#include "win.h"
#include "gfx.h"
// #include "x_model.h"
// #include "x_scene.h"

static HWND handle = NULL;
static LPTSTR classname = TEXT("XNALara_MainWindow");
static LPTSTR title = TEXT("XNALara (Direct3D 11)");

// mouse-tracking variables
static bool is_tracking = false;
static sint32 track_prev_x = -1;
static sint32 track_prev_y = -1;
static sint32 track_flags = 0;
static sint32 track_dx = 0;
static sint32 track_dy = 0;

static WINDOW_PROCEDURE(MainWindowProc);
static WINDOW_MESSAGE(EvNCCreate);
static WINDOW_MESSAGE(EvCreate);
static WINDOW_MESSAGE(EvDestroy);
static WINDOW_MESSAGE(EvNCDestroy);
static WINDOW_MESSAGE(EvPaint);
static WINDOW_MESSAGE(EvSize);
static WINDOW_MESSAGE(EvLButtonDown);
static WINDOW_MESSAGE(EvLButtonUp);
static WINDOW_MESSAGE(EvMButtonDown);
static WINDOW_MESSAGE(EvMButtonUp);
static WINDOW_MESSAGE(EvRButtonDown);
static WINDOW_MESSAGE(EvRButtonUp);
static WINDOW_MESSAGE(EvMouseMove);
static WINDOW_MESSAGE(EvCaptureChanged);
static WINDOW_MESSAGE(EvCancelMode);
static WINDOW_MESSAGE(EvCommand);
static WINDOW_COMMAND(CmOpenMesh);

BOOL CreateMainWindow(void)
{
 // already exists
 if(handle) return FALSE;

 // register window class
 WNDCLASSEX wcx;
 if(GetClassInfoEx(GetInstance(), classname, &wcx) == FALSE) {
    wcx.cbSize = sizeof(WNDCLASSEX);
    wcx.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;
    wcx.lpfnWndProc = (WNDPROC)MainWindowProc;
    wcx.cbClsExtra = 0;
    wcx.cbWndExtra = 0;
    wcx.hInstance = GetInstance();
    wcx.hIcon = NULL;
    wcx.hCursor = LoadCursor(NULL, IDC_ARROW);
    wcx.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
    wcx.lpszMenuName = TEXT("MAINMENU");
    wcx.lpszClassName = classname;
    wcx.hIconSm = NULL;
    if(RegisterClassEx(&wcx) == FALSE) {
       MessageBox(0, TEXT("Failed to register window class."), TEXT("Error"), MB_ICONSTOP);
       return FALSE;
      }
   }

 // create window
 DWORD styleEx = 0;
 DWORD style = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
 int x = CW_USEDEFAULT; int y = CW_USEDEFAULT;
 int w = CW_USEDEFAULT; int h = CW_USEDEFAULT;
 HWND hwnd = CreateWindowEx(styleEx, classname, title, style, x, y, w, h, NULL, NULL, GetInstance(), NULL);
 if(!hwnd) return FALSE;

 // initialize graphics
 if(InitD3D() == FALSE) return FALSE;
 return TRUE;
}

static LRESULT BeginMouseTracking(HWND window, WPARAM wparam, LPARAM lparam)
{
 SetCapture(window);
 is_tracking = true;
 track_flags = wparam;
 track_prev_x = LOWORD(lparam);
 track_prev_y = HIWORD(lparam);
 track_dx = 0;
 track_dy = 0;
 return 0;
}

static LRESULT EndMouseTracking(void)
{
 ReleaseCapture();
 is_tracking = false;
 track_flags = 0;
 track_prev_x = -1;
 track_prev_y = -1;
 track_dx = 0;
 track_dy = 0;
 return 0;
}

WINDOW_PROCEDURE(MainWindowProc)
{
 BEGIN_MESSAGE_HANDLER
  WINDOW_MESSAGE_HANDLER(WM_NCCREATE, EvNCCreate);
  WINDOW_MESSAGE_HANDLER(WM_CREATE, EvCreate);
  WINDOW_MESSAGE_HANDLER(WM_DESTROY, EvDestroy);
  WINDOW_MESSAGE_HANDLER(WM_NCDESTROY, EvNCDestroy);
  WINDOW_MESSAGE_HANDLER(WM_PAINT, EvPaint);
  WINDOW_MESSAGE_HANDLER(WM_SIZE, EvSize);
  WINDOW_MESSAGE_HANDLER(WM_LBUTTONDOWN, EvLButtonDown);
  WINDOW_MESSAGE_HANDLER(WM_LBUTTONUP, EvLButtonUp);
  WINDOW_MESSAGE_HANDLER(WM_MBUTTONDOWN, EvMButtonDown);
  WINDOW_MESSAGE_HANDLER(WM_MBUTTONUP, EvMButtonUp);
  WINDOW_MESSAGE_HANDLER(WM_RBUTTONDOWN, EvRButtonDown);
  WINDOW_MESSAGE_HANDLER(WM_RBUTTONUP, EvRButtonUp);
  WINDOW_MESSAGE_HANDLER(WM_CAPTURECHANGED, EvCaptureChanged);
  WINDOW_MESSAGE_HANDLER(WM_CANCELMODE, EvCancelMode);
  WINDOW_MESSAGE_HANDLER(WM_MOUSEMOVE, EvMouseMove);
  WINDOW_MESSAGE_HANDLER(WM_COMMAND, EvCommand);
  WINDOW_MESSAGE_DEFAULT;
 END_MESSAGE_HANDLER
}

WINDOW_MESSAGE(EvNCCreate)
{
 ::handle = window;
 SetMainWindow(::handle);
 return DefWindowProc(window, WM_NCCREATE, wparam, lparam);
}

WINDOW_MESSAGE(EvCreate)
{
 LRESULT retval = DefWindowProc(window, WM_CREATE, wparam, lparam);
 if(retval == -1) return MessageBox(window, TEXT("Failed to create window."), TEXT("Error"), MB_ICONSTOP);
 return retval;
}

WINDOW_MESSAGE(EvDestroy)
{
 // ClearScene();
 FreeD3D();
 return DefWindowProc(window, WM_DESTROY, wparam, lparam);
}

WINDOW_MESSAGE(EvNCDestroy)
{
 LRESULT retval = DefWindowProc(window, WM_NCDESTROY, wparam, lparam);
 SetMainWindow(NULL);
 ::handle = NULL;
 PostQuitMessage(0);
 return retval;
}

WINDOW_MESSAGE(EvPaint)
{
 // tell system we are done painting
 ValidateRect(window, NULL);
 return 0;
}

WINDOW_MESSAGE(EvSize)
{
 LRESULT retval = DefWindowProc(window, WM_SIZE, wparam, lparam);
 int dx = LOWORD(lparam);
 int dy = HIWORD(lparam);
 if(dx < 1) dx = 1;
 if(dy < 1) dy = 1;
 ResizeD3D(dx, dy);
 return retval;
}

WINDOW_MESSAGE(EvLButtonDown)
{
 return BeginMouseTracking(window, wparam, lparam);
}

WINDOW_MESSAGE(EvLButtonUp)
{
 return EndMouseTracking();
}

WINDOW_MESSAGE(EvMButtonDown)
{
 return BeginMouseTracking(window, wparam, lparam);
}

WINDOW_MESSAGE(EvMButtonUp)
{
 return EndMouseTracking();
}

WINDOW_MESSAGE(EvRButtonDown)
{
 return BeginMouseTracking(window, wparam, lparam);
}

WINDOW_MESSAGE(EvRButtonUp)
{
 return EndMouseTracking();
}

WINDOW_MESSAGE(EvMouseMove)
{
 // mouse position and flags
 WPARAM flags = wparam;
 WORD mx = LOWORD(lparam);
 WORD my = HIWORD(lparam);

 // if tracking
 if(is_tracking)
   {
    // set tracking flags
    track_flags = flags;

    // set tracking delta
    track_dx = mx - track_prev_x;
    track_dy = my - track_prev_y;

    // set tracking position
    track_prev_x = mx;
    track_prev_y = my;

    // L_BUTTON + ?
    if(track_flags & MK_LBUTTON)
      {
       // L_BUTTON + M_BUTTON
       if(track_flags & MK_MBUTTON) {
         }
       // L_BUTTON + R_BUTTON
       else if(track_flags & MK_RBUTTON) {
         }
       // L_BUTTON
       else {
         }
      }
    // M_BUTTON + ?
    else if(track_flags & MK_MBUTTON)
      {
       // M_BUTTON + R_BUTTON
       if(track_flags & MK_RBUTTON) {
         }
       // M_BUTTON
       else {
          // if(track_flags & MK_SHIFT) MouseTranslateScene(track_dx, track_dy);
          // else MouseRotateScene(track_dx, track_dy);
         }
      }
    // R_BUTTON
    else if(track_flags & MK_RBUTTON)
      {
      }
    // nothing is pressed
    else
       return EndMouseTracking();
   }
 // if not tracking
 else if(GetCapture() == window)
    ReleaseCapture();

 return 0;
}

WINDOW_MESSAGE(EvCaptureChanged)
{
 // disable mouse-tracking
 if(is_tracking) EndMouseTracking();
 return DefWindowProc(window, WM_CAPTURECHANGED, wparam, lparam);
}

WINDOW_MESSAGE(EvCancelMode)
{
 return EndMouseTracking();
}

WINDOW_MESSAGE(EvCommand)
{
 BEGIN_COMMAND_HANDLER
  WINDOW_COMMAND_HANDLER(CM_OPEN_MESH, CmOpenMesh);
 END_COMMAND_HANDLER 
 return 0;
}

WINDOW_COMMAND(CmOpenMesh)
{
 // BOOL success = LoadMeshBIN(TEXT("C:\\Users\\semory\\Desktop\\semory\\XNALara\\data\\rexil_raiden\\generic_item.mesh"));
 // if(success) MessageBox(window, TEXT("Succesfully loaded mesh binary."), TEXT(""), MB_OK);
 return 0;
}